package camid.distribution.activeobject;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;


public class ObjectRegistry {

	private Map<String, ObjectScheduler> idMap;
	private Map<Class<?>, List<ObjectScheduler>> definitionMap;
	
	private ReadWriteLock lock;
	private Lock readLock;
	private Lock writeLock;
	
	public ObjectRegistry()
	{
		idMap = new HashMap<String, ObjectScheduler>();
		definitionMap = new HashMap<Class<?>, List<ObjectScheduler>> ();
		lock = new ReentrantReadWriteLock();
		writeLock = lock.writeLock();
		readLock = lock.readLock();
		
	}
	
	public void add(ObjectScheduler objectScheduler) 
	{
		try 
		{
			writeLock.lock();
			idMap.put(objectScheduler.getObjectId(), objectScheduler);
			addOnDefinitionMap(objectScheduler);
		}
		finally
		{
			writeLock.unlock();
		}
	}

	public boolean contains(String objectId) 
	{
		boolean result = false;
		try 
		{
			readLock.lock();
			result = idMap.containsKey(objectId);
		} 
		finally
		{
			readLock.unlock();
		}
		return result;
	}

	public void shutdown() 
	{
		try 
		{
			writeLock.lock();
			Iterator<Entry<String,ObjectScheduler>> iterator = idMap.entrySet().iterator();
			while(iterator.hasNext())
			{
				Entry<String,ObjectScheduler> entry = iterator.next();
				ObjectScheduler scheduler = entry.getValue();
				scheduler.shutdown();
				iterator.remove();
			}
		}
		finally
		{
			writeLock.unlock();
		}
	}

	public ObjectScheduler remove(String objectId) 
	{
		ObjectScheduler scheduler = null;
		try 
		{
			writeLock.lock();
			scheduler = idMap.remove(objectId);
			removeFromDefinitionMap(scheduler.getEntityClass(), objectId);
			scheduler.shutdown();
		}
		finally
		{
			writeLock.unlock();
		}
		return scheduler;
	}

	public ObjectScheduler get(String objectId) 
	{
		ObjectScheduler scheduler = null;
		try
		{
			readLock.lock();
			scheduler = idMap.get(objectId);
		}
		finally
		{
			readLock.unlock();
		}
		return scheduler;
	}

	public List<ObjectScheduler> getByClass(Class<?> entityClass) 
	{
		List<ObjectScheduler> schedulerList = null;
		try
		{
			readLock.lock();
			schedulerList = definitionMap.get(entityClass);
			if( schedulerList == null)
				schedulerList = new ArrayList<ObjectScheduler> ();
		}
		finally
		{
			readLock.unlock();
		}
		
		return schedulerList;
	}

	private void removeFromDefinitionMap(Class<?> entityClass, String objectId)
	{
		List<ObjectScheduler> schedulerList = definitionMap.get(entityClass);
		if(schedulerList != null)
		{
			Iterator<ObjectScheduler> iterator = schedulerList.iterator();
			while(iterator.hasNext())
			{
				ObjectScheduler scheduler = iterator.next();
				if(scheduler.getObjectId().equals(objectId))
				{
					iterator.remove();
				}
			}
		}
	}
	
	
	private void addOnDefinitionMap(ObjectScheduler scheduler)
	{
		Class<?> entityClass = scheduler.getEntityClass();
		List<ObjectScheduler> list = definitionMap.get(entityClass);
		if(list == null)
		{
			list = new ArrayList<ObjectScheduler>();
			definitionMap.put(entityClass, list);
		}
		list.add(scheduler);
	}

	public List<ObjectScheduler> getSchedulers() 
	{
		List<ObjectScheduler> list = new ArrayList<ObjectScheduler> (this.idMap.size());
		try 
		{
			readLock.lock();
			for(Entry<String,ObjectScheduler> entry : idMap.entrySet())
			{
				list.add( entry.getValue() );
			}
		}
		finally
		{
			readLock.unlock();
		}
		return list;
	}

}
